package com.lexc.watermq.broker.core;

import com.lexc.watermq.broker.cache.CommonCache;
import com.lexc.watermq.broker.constants.BrokerConstants;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;

/**
 * createTime：2025-08-18 10:19
 * description：基础的mmap模型
 */
public class MMapFileModel {
    private File file;
    private MappedByteBuffer mappedByteBuffer;
    private FileChannel fileChannel;

    private String topicName;

    /**
     * 指定offset做文件的映射
     *
     * @param topicName   主题名称
     * @param startOffset 读取的开始位置
     * @param mapSize     读取的大小(byte)
     */
    public void loadFileInMMap(String topicName, int startOffset, int mapSize) throws IOException {

        String filePath = CommonCache.getGlobalProperties().getWaterMQHome()
                + BrokerConstants.BASE_STORE_PATH.getVal()
                + topicName;

        file = new File(filePath);
        if (!file.exists()) {
            throw new FileNotFoundException("file path " + filePath + " not exist");
        }
        RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw");
        this.fileChannel = randomAccessFile.getChannel();

        this.mappedByteBuffer = this.fileChannel.map(FileChannel.MapMode.READ_WRITE,
                startOffset, mapSize);
    }

    /**
     * 文件从指定的offset开始写入
     *
     * @param content 写入的内容
     * @param force   是否强制刷磁盘
     */
    public void writeContent(byte[] content, boolean force) {
        //默认刷新到page cache
        mappedByteBuffer.put(content);
        if (force) {
//强制刷入磁盘
            mappedByteBuffer.force();
        }
    }

    public byte[] readContent(int readOffset, int size) {
        //直接定义读取的位置
        mappedByteBuffer.position(readOffset);
        byte[] content = new byte[size];
        int j = 0;
//        从内存中读取
        for (int i = 0; i < size; i++) {
            byte b = mappedByteBuffer.get(readOffset + i);
            content[j++] = b;
        }
        return content;
    }
}
